package com.navi.loaddata.loadService.impl.Dcdata;

import com.navi.loaddata.core.errorLog.ErrorCode;
import com.navi.loaddata.core.etlException.ETLException2;
import com.navi.loaddata.core.gpEntity.MParamD;
import com.navi.loaddata.core.mesEntity.SpcChartMShopEqpt;
import com.navi.loaddata.core.mesEntity.SpcDcResultData;
import com.navi.loaddata.core.mesEntity.SpcDcdata;
import com.navi.loaddata.core.mysqlEntity.EtlConfDModel;
import com.navi.loaddata.core.oracleEntity.*;
import com.navi.loaddata.core.oracleEntity.base.EtlParamV;
import com.navi.loaddata.core.util.LoggerUtil;
import com.navi.loaddata.core.util.ProcessUtil;
import com.navi.loaddata.loadDao.SaveBaseDataDao;
import com.navi.loaddata.loadDao.SavePdsDataDao;
import com.navi.loaddata.loadService.impl.baseData.LoadMesBaseDataService;
import com.navi.loaddata.loadService.impl.baseData.ProcessBaseDataService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.navi.loaddata.core.constant.GenericDef.*;
import static java.util.stream.Collectors.groupingBy;

/**
 * @author jay
 */
@Service
public class LoadDcDataService {
    private static final Logger logger = LoggerFactory.getLogger(LoadDcDataService.class);
    private LoggerUtil loggerUtil = new LoggerUtil(this.getClass());

    @Autowired
    private LoadMesBaseDataService loadMesBaseDataService;
    @Autowired
    private SaveBaseDataDao saveBaseDataDao;
    @Autowired
    private ProcessBaseDataService processBaseDataService;
    @Autowired
    private ProcessDcDataServiceP processDcDataServiceP;
    @Autowired
    private ProcessDcDataServiceI processDcDataServiceI;
    @Autowired
    private LoadDcInfoService loadDcInfoService;
    @Autowired
    private CheckDcDataService checkDcDataService;
    @Autowired
    private SavePdsDataDao savePdsDataDao;

    public String[] loadDcDataMain(EtlConfDModel etlConfD) throws Exception {
        String[] resMsg = loadDcData(etlConfD);
        String msg = etlConfD.getEqpt();
        if (StringUtils.isEmpty(etlConfD.getEqpt())) msg = "ALL";
        logger.info("Eqpt={} loadDcDataMain finish!", msg);
        return resMsg;
    }

    /**
     * Load Dc Data
     *
     * @param etlConfD
     */
    private String[] loadDcData(EtlConfDModel etlConfD) throws Exception {
        String[] resMsg = new String[3];
        int okCnt = 0;
        int errCnt = 0;
        String errMsg = null;

        // DcData
        List<String> unitnameList = loadDcInfoService.getUnitNameList(etlConfD);
        List<SpcDcdata> spcDcdataList = loadDcInfoService.loadDcDataList(etlConfD, "'" + DCTYPE_I + "','" + DCTYPE_P + "'", unitnameList);
        logger.info("Spc Dcdata count {}", spcDcdataList.size());
        if (!spcDcdataList.isEmpty()) {

            // base
            List<EtlStepV> etlStepVList = loadMesBaseDataService.loadAllFinalStep(etlConfD.getShop());
            List<EtlProductV> etlProductVList = loadMesBaseDataService.loadAllFinalProduct(etlConfD.getShop());
            saveBaseDataDao.saveBaseData(etlConfD, etlStepVList, etlProductVList);

            //getItemName  from Mysql
            HashMap<String, List<String>> subeqItemName = loadDcInfoService.getItemNames(etlConfD);
            if (subeqItemName.isEmpty()) throw new ETLException2(ErrorCode.ERROR_SET_MYSQL_PDS_CONF_D, null);

            //getUcl,Usl

            HashMap<String, SpcChartMShopEqpt> spcChartMMap = loadDcInfoService.getSpcChartMMap(subeqItemName);
            // DcData
            for (SpcDcdata spcDc : spcDcdataList) {
                //站点限制
                if (true == (ProcessUtil.opeLimit(spcDc.getProcessoperationname()))) {
                    logger.warn("glassId={} opeId={} 站点信息错误。忽略。", spcDc.getMaterialname(), spcDc.getProcessoperationname());
                    errCnt++;
                    continue;
                }
                try {
                    savePdsDataDao.deletePds(etlConfD);
                } catch (ETLException2 e) {
                    logger.error("{} 失败原因：{}", e.getErrorCode().getErrorMsg(), LoggerUtil.stackTraceToString(e));
                    if (StringUtils.isEmpty(errMsg)) {
                        errMsg = e.getErrorCode().getErrorMsg() + "错误原因：" + e.getErrMsg();
                    } else {
                        errMsg += e.getErrorCode().getErrorMsg() + "错误原因：" + e.getErrMsg();
                    }
                    errCnt++;
                    continue;
                }


                try {
//                    getPDSresult
                    List<SpcDcResultData> spcDcResultDataList = new ArrayList<>();
                    String unitname = spcDc.getUnitname().substring(0, 4) + "*" + spcDc.getUnitname().substring(6, 8);
                    if (null == subeqItemName.get(unitname)) {
                        logger.error("PDS ETL UNITNAME={} 配置不正确", unitname);
                        continue;
                    }
                    if (DCTYPE_P.equals(spcDc.getDctype())) {
                        spcDcResultDataList = loadDcInfoService.loadPDataList(etlConfD, spcDc.getDcdataid(), subeqItemName.get(unitname));

                        if (spcDcResultDataList.isEmpty()) {
                            logger.warn("dcDataId=" + spcDc.getDcdataid() + " 对应的 spcDcResultDataList 为空，跳过。");
                            continue;
                        }

                        //process
                        EtlPdsGlassV etlPdsGlassV = processDcDataServiceP.processDcData(etlConfD, spcDc);

                        List<EtlPdsResultV> etlPdsResultVList = new ArrayList<>();
                        List<EtlPdsGlassSummaryV> etlPdsGlassSummaryVList = new ArrayList<>();

                        String paramCollection = spcDc.getRecipename();
                        if (StringUtils.isEmpty(paramCollection)) {
//                            paramCollection = spcDc.getProductspecname();
                            // 如果recipe为空，次笔数据不处理  改为赋值productId
                            logger.warn("DCDATAID={} recipe为空，", spcDc.getDcdataid());
                            continue;
                        }


                        //同一dcdataId 批量处理他的result,summary
                        Map<String, List<SpcDcResultData>> mDataTree =
                                spcDcResultDataList.stream().collect(groupingBy(SpcDcResultData::getItemname));

                        for (Map.Entry<String, List<SpcDcResultData>> entry : mDataTree.entrySet()) {
                            EtlPdsGlassSummaryV etlPdsGlassSummaryV = new EtlPdsGlassSummaryV();
                            List<SpcDcResultData> curDcDataList = entry.getValue();


                            // 数据检查
                            boolean[] resCheck = checkDcDataService.checkDcData(curDcDataList, spcDc);
                            boolean isCheck = resCheck[0];
                            boolean isRawData = resCheck[1];
                            boolean isXData = resCheck[2];
                            boolean isAscData = resCheck[3];

                            if (!isCheck) continue;


                            int resultListCnt = curDcDataList.size();
                            SpcDcResultData firstResult = curDcDataList.get(0);
////70111625
//                            if (spcDc.getDcdataid() != 70111624) {
//                                continue;
//                            }
//                            System.out.println("x");
                            // 赋值
                            etlPdsGlassSummaryV = processDcDataServiceP.processPdsGlassSummary(etlPdsGlassV, paramCollection, firstResult);
                            for (int j = 0; j < resultListCnt; j++) {
                                SpcDcResultData curResult = curDcDataList.get(j);
                                String curSiteName = curResult.getSitename();
                                Double resVal = ProcessUtil.getDouble(curResult.getResult());
                                if (isRawData) {
                                    if (ProcessUtil.isNumeric(curSiteName)) {
                                        // 数字类型 raw data
                                        //制成没有RESULT
                                    } else if (SUM_SITE_LIST.contains(curSiteName)) {
                                        // 预定义的SUM类型
                                        if (SITE_AVG.equals(curSiteName)) {
                                            etlPdsGlassSummaryV.setAvg(resVal);
                                        } else if (SITE_MAX.equals(curSiteName)) {
                                            etlPdsGlassSummaryV.setMax(resVal);
                                        } else if (SITE_MIN.equals(curSiteName)) {
                                            etlPdsGlassSummaryV.setMin(resVal);
                                        } else if (SITE_SDV.equals(curSiteName)) {
                                            etlPdsGlassSummaryV.setStd(resVal);
                                            etlPdsGlassSummaryV.setThreeSigma(resVal * 3);
                                        } else if (SITE_RNG.equals(curSiteName)) {
                                            etlPdsGlassSummaryV.setRange(resVal);
                                        } else if (SITE_U1.equals(curSiteName)) {
                                            etlPdsGlassSummaryV.setUniformity1(resVal);
                                        } else if (SITE_U2.equals(curSiteName)) {
                                            etlPdsGlassSummaryV.setUniformity2(resVal);
                                        }
                                    } else {
                                        logger.error("Raw data 包含无效的字符串，DCDATAID: {}， Site name {}", spcDc.getDcdataid(), curSiteName);
                                    }
                                } else if (isXData) {
                                    etlPdsGlassSummaryV.setParamValue(resVal);
                                    etlPdsGlassSummaryV.setMax(resVal);
                                    etlPdsGlassSummaryV.setMin(resVal);
                                    etlPdsGlassSummaryV.setAvg(resVal);
                                    etlPdsGlassSummaryV.setDataQty(1.0);
                                } else if (isAscData) {
                                    etlPdsGlassSummaryV.setParamValue2(curResult.getResult());
                                    etlPdsGlassSummaryV.setDataQty(0.0);
                                }
                            }
                            if (isRawData) {
                                etlPdsGlassSummaryV.setDataQty((double) etlPdsResultVList.size());
                                etlPdsGlassSummaryV.setParamValue(etlPdsGlassSummaryV.getAvg());
                            }
                            etlPdsGlassSummaryVList.add(etlPdsGlassSummaryV);

                        }// End of for Map

                        // PARAM
                        List<EtlParamV> etlParamList = processBaseDataService.processParamInfoP(etlPdsGlassSummaryVList);
                        saveBaseDataDao.deleteParam(etlConfD);
                        saveBaseDataDao.saveParamData(etlConfD, etlParamList);

                        savePdsDataDao.savePdsDataP(etlConfD, etlPdsGlassV, etlPdsGlassSummaryVList, etlPdsResultVList);
                        logger.info("pdsGlassId={} step_id={} dcdataId={} 保存成功！", spcDc.getMaterialname(), spcDc.getProcessoperationname(), spcDc.getDcdataid());

                        //良测
                    } else if (DCTYPE_I.equals(spcDc.getDctype())) {
                        spcDcResultDataList = loadDcInfoService.loadMDataList(etlConfD, spcDc.getDcdataid(), subeqItemName.get(unitname));
                        if (spcDcResultDataList.isEmpty()) {
                            logger.warn("dcDataId=" + spcDc.getDcdataid() + " 对应的 spcDcResultDataList 为空，跳过。");
                            continue;
                        }

                        //process
                        EtlGlassV etlGlassV = processDcDataServiceI.processDcData(etlConfD, spcDc);

                        List<EtlResultV> etlResultVList = new ArrayList<>();
                        List<EtlGlassSummaryV> etlGlassSummaryVList = new ArrayList<>();

                        String paramCollection = spcDc.getRecipename();
                        if (StringUtils.isEmpty(paramCollection)) {
//                            paramCollection = spcDc.getProductspecname();
                            // 如果recipe为空，次笔数据不处理  改为赋值productId
                            logger.warn("DCDATAID={} recipe为空，", spcDc.getDcdataid());
                            continue;
                        }


                        //同一dcdataId 批量处理他的result,summary
                        Map<String, List<SpcDcResultData>> mDataTree =
                                spcDcResultDataList.stream().collect(groupingBy(SpcDcResultData::getItemname));

                        for (Map.Entry<String, List<SpcDcResultData>> entry : mDataTree.entrySet()) {
                            EtlGlassSummaryV etlGlassSummaryV = new EtlGlassSummaryV();
                            List<SpcDcResultData> curDcDataList = entry.getValue();


                            //赋值
                            // 数据检查
                            boolean[] resCheck = checkDcDataService.checkDcData(curDcDataList, spcDc);
                            boolean isCheck = resCheck[0];
                            boolean isRawData = resCheck[1];
                            boolean isXData = resCheck[2];
                            boolean isAscData = resCheck[3];

                            if (!isCheck) continue;


                            int resultListCnt = curDcDataList.size();
                            SpcDcResultData firstResult = curDcDataList.get(0);

                            // 赋值
                            etlGlassSummaryV = processDcDataServiceI.processGlassSummary(etlGlassV, paramCollection, firstResult);
                            for (int j = 0; j < resultListCnt; j++) {
                                SpcDcResultData curResult = curDcDataList.get(j);
                                String curSiteName = curResult.getSitename();
                                Double resVal = ProcessUtil.getDouble(curResult.getResult());
                                if (isRawData) {
                                    if (ProcessUtil.isNumeric(curSiteName)) {
                                        // 数字类型 raw data
                                        EtlResultV result = processDcDataServiceI.processResultData(etlConfD, spcDc, paramCollection, curResult);
                                        etlResultVList.add(result);

                                    } else if (SUM_SITE_LIST.contains(curSiteName)) {
                                        // 预定义的SUM类型
                                        if (SITE_AVG.equals(curSiteName)) {
                                            etlGlassSummaryV.setAvg(resVal);
                                        } else if (SITE_MAX.equals(curSiteName)) {
                                            etlGlassSummaryV.setMax(resVal);
                                        } else if (SITE_MIN.equals(curSiteName)) {
                                            etlGlassSummaryV.setMin(resVal);
                                        } else if (SITE_SDV.equals(curSiteName)) {
                                            etlGlassSummaryV.setStd(resVal);
                                            etlGlassSummaryV.setThreeSigma(resVal * 3);
                                        } else if (SITE_RNG.equals(curSiteName)) {
                                            etlGlassSummaryV.setRange(resVal);
                                        }
//                                        else if (SITE_U1.equals(curSiteName)) {
//                                            etlGlassSummaryV.setUniformity1(resVal);
//                                        } else if (SITE_U2.equals(curSiteName)) {
//                                            etlGlassSummaryV.setUniformity2(resVal);
//                                        }
                                    } else {
                                        logger.error("Raw data 包含无效的字符串，DCDATAID: {}， Site name {}", spcDc.getDcdataid(), curSiteName);
                                    }
                                } else if (isXData) {
                                    etlGlassSummaryV.setParamValue(resVal);
                                    etlGlassSummaryV.setMax(resVal);
                                    etlGlassSummaryV.setMin(resVal);
                                    etlGlassSummaryV.setAvg(resVal);
//                                    etlGlassSummaryV.setDataQty(1.0);
                                }
//                                else if (isAscData) {
//                                    etlGlassSummaryV.setParamValue2(curResult.getResult());
//                                    etlGlassSummaryV.setDataQty(0.0);
//                                }
                            }
                            if (isRawData) {
//                                etlGlassSummaryV.setDataQty((double) etlResultVList.size());
                                etlGlassSummaryV.setParamValue(etlGlassSummaryV.getAvg());
                            }
                            etlGlassSummaryV = processDcDataServiceI.setSpcChartM(etlGlassSummaryV, spcChartMMap);
                            etlGlassSummaryVList.add(etlGlassSummaryV);
                        }
                        // PARAM
                        List<EtlParamV> etlParamList = processBaseDataService.processParamInfoI(etlGlassSummaryVList);
                        saveBaseDataDao.deleteParam(etlConfD);
                        saveBaseDataDao.saveParamData(etlConfD, etlParamList);

                        savePdsDataDao.savePdsDataI(etlConfD, etlGlassV, etlGlassSummaryVList, etlResultVList);
                        logger.info("glassId={} step_id={} dcdataId={} 保存成功！", spcDc.getMaterialname(), spcDc.getProcessoperationname(), spcDc.getDcdataid());
                    }
                } catch (ETLException2 e) {
                    logger.error("dcDataId=" + spcDc.getDcdataid() + " " + e.getErrorCode().getErrorMsg() + "错误原因：\n" + LoggerUtil.stackTraceToString(e));
                    if (StringUtils.isEmpty(errMsg)) {
                        errMsg = "dcDataId=" + spcDc.getDcdataid() + " " + e.getErrorCode().getErrorMsg() + "错误原因：" + e.getErrMsg();
                    } else {
                        errMsg += "dcDataId=" + spcDc.getDcdataid() + " " + e.getErrorCode().getErrorMsg() + "错误原因：" + e.getErrMsg();
                    }
                    errCnt++;
                    continue;
                }


                // end of for curDCList

            }
        } else {
            logger.info("没有此区间的数据。"); // todo print log & save etl data
        }
        resMsg[0] = String.valueOf(okCnt);
        resMsg[1] = String.valueOf(errCnt);
        resMsg[2] = errMsg;
        return resMsg;
    }

//    public List<String> getDistinctOpes(EtlConfD etlConfD) {
//        List<String> opes=loadDcInfoService.getDistinctOpes(etlConfD);
//        return opes;
//    }
}
